#include <iostream>
#include <memory>
#include <vector>

using std::cout;
using std::endl;
using std::shared_ptr;
using std::vector;

//共享所有权，采用引用计数
//允许复制和赋值
//有移动语义
//作为容器元素时，既可以传递左值，也可以传递右值(因为有拷贝构造函数，可以直接push_back)
//有几块空间就构造、析构几次

class Point{
public:
    Point(int ix, int iy): _ix(ix),_iy(iy)
    {
        cout<<"Point(int, int)"<<endl;
    }
    ~Point(){
        cout<<"~Point()"<<endl;
    }

    void print() const{
        cout<<"("<<_ix<<','<<_iy<<")"<<endl;
    }

private:
    int _ix;
    int _iy;
};

void test(){
    shared_ptr<Point> sp(new Point(111,222)); //智能指针
    cout<<"*sp=";
    sp->print();
    cout<<"sp.get()="<<sp.get()<<endl;
    cout<<"sp.use_count() = "<<sp.use_count()<<endl;

    cout<<endl;
    shared_ptr<Point> sp2(sp);   //允许复制
    cout<<"*sp=";
    sp->print();
    cout<<"*sp2=";
    sp2->print();
    cout<<"sp.get()="<<sp.get()<<endl;
    cout<<"sp2.get()="<<sp2.get()<<endl;
    cout<<"sp.use_count() = "<<sp.use_count()<<endl;
    cout<<"sp2.use_count() = "<<sp2.use_count()<<endl;
    
    cout<<endl;
    shared_ptr<Point> sp3(new Point(333,444));
    cout<<"*sp3=";
    sp3->print();
    cout<<"sp3.get()="<<sp3.get()<<endl;
    cout<<"sp3.use_count() = "<<sp3.use_count()<<endl;
    
    cout<<endl;
    sp3=sp; //  允许赋值，此时(333,444)空间自动析构
    cout<<"*sp=";
    sp->print();
    cout<<"*sp2=";
    sp2->print();
    cout<<"*sp3=";
    sp3->print();
    cout<<"sp.get()="<<sp.get()<<endl;
    cout<<"sp2.get()="<<sp2.get()<<endl;
    cout<<"sp3.get()="<<sp3.get()<<endl;
    cout<<"sp.use_count() = "<<sp.use_count()<<endl;
    cout<<"sp2.use_count() = "<<sp2.use_count()<<endl;
    cout<<"sp3.use_count() = "<<sp3.use_count()<<endl;

    cout<<endl;
    vector<shared_ptr<Point>> vec;

    //push_back传入参数时调用拷贝构造函数
    vec.push_back(sp);
    
    //而shared_ptr有移动语义，所以传入右值即可
    vec.push_back(std::move(sp));

    //直接传入临时对象
    vec.push_back(shared_ptr<Point> (new Point(555,666)));
    
    cout<<"此时还剩两块空间，(111,222)、(555,666)，所以析构两次"<<endl;
}

int main()
{   
    test();
    return 0;
}

